﻿// -----------------------------------------------------------------------
// <copyright file="SysConfigMateOperation.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

using BasicFrameworkDemo.Utility;

namespace BasicFrameworkDemo.BLL
{
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Linq;
    using System.Text;
    using System.Xml;



    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    /// <author>
    /// LiLei
    /// </author>
    public class SysConfigMateOperation : IConfigMateOperation
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="XmlConfigMateOperation"/> class.
        /// </summary>
        /// Creator:LiLei
        /// CreationDate:7/14/2012 4:33 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        public SysConfigMateOperation()
        {

        }

        /// <summary>
        /// Sets the app setting value.
        /// </summary>
        /// <param name="needModificationSettings">The need modification settings.</param>
        /// Creator:LiLei
        /// CreationDate:7/14/2012 3:00 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        /// Creator:LiLei
        /// CreationDate:7/14/2012 3:02 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        public void SetAppSettingValue(Dictionary<string, string> needModificationSettings)
        {
            string configFilePath;
            var webConfig = this.GetConfigXmlFile(out configFilePath);

            foreach (var needModificationSetting in needModificationSettings)
            {
                var appSettings = webConfig.SelectSingleNode(SystemConfig.XmlConfigurationRootNodeName);
                // ReSharper disable PossibleNullReferenceException
                var existNode = appSettings.SelectSingleNode("add[@key='" + needModificationSetting.Key + "']");
                // ReSharper restore PossibleNullReferenceException
                // ReSharper disable PossibleNullReferenceException
                existNode.Attributes["value"].Value = needModificationSetting.Value;
                // ReSharper restore PossibleNullReferenceException
            }

            webConfig.Save(configFilePath);
        }

        /// <summary>
        /// Gets the config XML file.
        /// </summary>
        /// <param name="configFilePath">The config file path.</param>
        /// <returns></returns>
        /// Creator:LiLei
        /// CreationDate:7/14/2012 5:30 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        private XmlDocument GetConfigXmlFile(out string configFilePath)
        {
            var webConfig = new XmlDocument();
            configFilePath = string.Format("{0}/{1}", AppDomain.CurrentDomain.BaseDirectory, SystemConfig.XmlConfigurationFile);
            webConfig.Load(configFilePath);
            return webConfig;
        }

        /// <summary>
        /// Gets the config XML file.
        /// </summary>
        /// <returns></returns>
        /// Creator:LiLei
        /// CreationDate:7/14/2012 5:34 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        private XmlDocument GetConfigXmlFile()
        {
            var webConfig = new XmlDocument();
            var configFilePath = string.Format("{0}/{1}", AppDomain.CurrentDomain.BaseDirectory, SystemConfig.XmlConfigurationFile);
            webConfig.Load(configFilePath);
            return webConfig;
        }

        /// <summary>
        /// Adds the app settings.
        /// </summary>
        /// <param name="needAddSettings">The need add settings.</param>
        /// Creator:LiLei
        /// CreationDate:7/14/2012 3:00 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        /// Creator:LiLei
        /// CreationDate:7/14/2012 3:02 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        public void AddAppSettings(Dictionary<string, string> needAddSettings)
        {
            string configFilePath;
            var webConfig = this.GetConfigXmlFile(out configFilePath);

            foreach (var needAddSetting in needAddSettings)
            {
                var appSettings = webConfig.SelectSingleNode(SystemConfig.XmlConfigurationRootNodeName);
                var newNode = webConfig.CreateElement("add");
                newNode.SetAttribute("key", needAddSetting.Key);
                newNode.SetAttribute("value", needAddSetting.Value);

                // ReSharper disable PossibleNullReferenceException
                var insertNode = appSettings.AppendChild(newNode);
                // ReSharper restore PossibleNullReferenceException
            }

            webConfig.Save(configFilePath);
        }

        /// <summary>
        /// filte the config paremeter
        /// </summary>
        /// <param name="configurationParas">The configuration paras.</param>
        /// <returns>filted config items</returns>
        /// Creator:LiLei
        /// CreationDate:7/11/2012 2:02 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        public Dictionary<string, string> ConfigFilter(Dictionary<string, string> configurationParas)
        {
            var filtedConfig = new Dictionary<string, string>();
            // ReSharper disable LoopCanBeConvertedToQuery
            // ReSharper disable PossibleNullReferenceException
            foreach (var configurationPara in configurationParas)
            // ReSharper restore PossibleNullReferenceException
            // ReSharper restore LoopCanBeConvertedToQuery
            {
                if (this.Exist(configurationPara.Key, configurationPara.Value))
                {
                    continue;
                }

                if (filtedConfig.ContainsKey(configurationPara.Key) && filtedConfig.ContainsValue(configurationPara.Value))
                {
                    continue;
                }

                filtedConfig.Add(configurationPara.Key, configurationPara.Value);
            }


            return filtedConfig;
        }

        /// <summary>
        /// Gets all config items.
        /// </summary>
        /// <returns></returns>
        /// Creator:LiLei
        /// CreationDate:7/11/2012 3:07 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        public Dictionary<string, string> GetAllConfigItems()
        {
            var webConfig = this.GetConfigXmlFile();
            var rootNode = webConfig.SelectSingleNode(SystemConfig.XmlConfigurationRootNodeName);
            if (rootNode == null)
            {
                return null;
            }

            var childNodes = rootNode.ChildNodes;
            if (childNodes.Count == 0)
            {
                return null;
            }

            var configItems = childNodes.Cast<XmlNode>().Where(nodes=>nodes.Attributes!=null).ToDictionary(
                childNode =>
                    childNode.Attributes["key"].Value, 
                    childNode =>
                        childNode.Attributes["value"].Value );

            return configItems;
        }

        /// <summary>
        /// Gets the specific config item.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        /// Creator:LiLei
        /// CreationDate:7/11/2012 3:08 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        public Dictionary<string, string> GetSpecificConfigItem(string key)
        {
            var webConfig = this.GetConfigXmlFile();
            var rootNode = webConfig.SelectSingleNode(SystemConfig.XmlConfigurationRootNodeName);
            var configItems = new Dictionary<string, string>();
            if (rootNode == null)
            {
                return null;
            }

            if (!rootNode.HasChildNodes)
            {
                return null;
            }

            var items = rootNode.SelectNodes("add[@key='" + key + "']");

            if (items == null || items.Count == 0)
            {
                return null;
            }

            foreach (XmlNode item in items)
            {
                // ReSharper disable PossibleNullReferenceException
                configItems.Add(item.Attributes["key"].Value, item.Attributes["value"].Value);
                // ReSharper restore PossibleNullReferenceException
            }

            return configItems;
        }

        /// <summary>
        /// Removes the items.
        /// </summary>
        /// <param name="keys">The keys.</param>
        /// Creator:LiLei
        /// CreationDate:7/14/2012 5:03 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        public void RemoveItems(string[] keys)
        {
            string filePath;
            var webConfig = this.GetConfigXmlFile(out filePath);
            var rootNode = webConfig.SelectSingleNode(SystemConfig.XmlConfigurationRootNodeName);

            foreach (var key in keys)
            {
                // ReSharper disable PossibleNullReferenceException
                var childNode = rootNode.SelectSingleNode("//add[@key='" + key + "']");
                // ReSharper restore PossibleNullReferenceException
                // ReSharper disable AssignNullToNotNullAttribute
                if (childNode == null)
                {
                    continue;
                }
                rootNode.RemoveChild(childNode);
                // ReSharper restore AssignNullToNotNullAttribute
            }

            webConfig.Save(filePath);
        }

        /// <summary>
        /// Exists the specified key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        /// Creator:LiLei
        /// CreationDate:7/14/2012 6:06 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        /// Creator:LiLei
        /// CreationDate:7/14/2012 6:07 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        public bool Exist(string key)
        {
            return !this.GetSpecificConfigItem(key).IsNullOrEmpty();
        }

        /// <summary>
        /// Exists the specified key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        /// Creator:LiLei
        /// CreationDate:7/14/2012 6:48 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        /// Creator:LiLei
        /// CreationDate:7/14/2012 6:52 PM
        /// Modify:
        /// ModifyDate:
        /// ----------------------------------------------------------------------------------------
        public bool Exist(string key, string value)
        {
            var webConfig = this.GetConfigXmlFile();
            var rootNode = webConfig.SelectSingleNode(SystemConfig.XmlConfigurationRootNodeName);
            var node = rootNode.SelectNodes("add[@key='" + key + "' and @value='" + value + "']");
            return !node.IsNullOrEmpty() && node.Count > 0;
        }
    }
}
